import os
import time
import pyautogui as pyg
import yaml
from pygetwindow import Win32Window
import pydirectinput as pdi


class Tools:

    def __init__(self, window: Win32Window, init_width: int, init_height: int):
        self.init_width = init_width
        self.init_height = init_height
        self.window = window
        self.default_region = (
            window.left, window.top, window.left + window.width + 50, window.top + window.height + 50)

    # 识图封装 300找图,，点一次，相似度0.9，像素步长5,不灰度
    def find_img_abs_path(self, path, count=10, confidence=0.95, region=None, grayscale=False, step=5):
        point = self.find_img_abs_path_point(path, confidence=confidence, region=region, grayscale=grayscale, step=step)
        return False if point is None else True
    def find_img_abs_muti_path_point(self, path_list:list, count=10, confidence=0.95, region=None, grayscale=False, step=5):
        if region is None:
            region = self.default_region
        for path in path_list:
            if not os.path.exists(path):
                print(f"文件 {path.split('/')[-1]} 不存在")
                raise FileNotFoundError(f"请输入存在的图片位置{path}")
        attempts = 1
        while attempts < count + 1:
            start_time = time.time()
            for path in path_list:
                try:
                    point = pyg.locateCenterOnScreen(
                        path, minSearchTime=0.1, confidence=confidence, region=region, grayscale=grayscale, step=step)
                    end_time = time.time()
                    print(
                        f"第{attempts}次 {path.split('/')[-1]} 识别成功 无点击耗时{end_time - start_time:.3f}，region:{region}")
                    return point
                except pyg.ImageNotFoundException:
                    pass
                    #not_find_time = time.time()
                    #print(f"第{attempts}次 {path.split('/')[-1]} 识别失败 耗时{not_find_time-start_time:.3f}，region:{region}")
            attempts += 1
        if attempts >= count:
            pass
            # print("未发现图片")
        return None
    # 识图封装 300找图,，点一次，相似度0.9，像素步长5,不灰度
    def find_img_abs_path_point(self, path, count=10, confidence=0.95, region=None, grayscale=False, step=5):
        if region is None:
            region = self.default_region
        if not os.path.exists(path):
            print(f"文件 {path.split('/')[-1]} 不存在")
            raise FileNotFoundError(f"请输入存在的图片位置{path}")
        attempts = 1
        while attempts < count + 1:
            start_time = time.time()
            try:
                point = pyg.locateCenterOnScreen(
                    path, minSearchTime=0.1, confidence=confidence, region=region, grayscale=grayscale, step=step)
                end_time = time.time()
                print(
                    f"第{attempts}次 {path.split('/')[-1]} 识别成功 无点击耗时{end_time - start_time:.3f}，region:{region}")
                return point
            except pyg.ImageNotFoundException:
                not_find_time = time.time()
                print(f"第{attempts}次 {path.split('/')[-1]} 识别失败 耗时{not_find_time-start_time:.3f}，region:{region}")
            attempts += 1
        if attempts >= count:
            pass
            # print("未发现图片")
        return None
    def find_img_rel_path_point(self, path, count=10, confidence=0.95, region=None, grayscale=False, step=5):
        abs_path = os.path.join(os.path.join(os.path.dirname(__file__), "image"), path)
        return self.find_img_abs_path_point(abs_path, count, confidence=confidence, region=region, grayscale=grayscale,
                                      step=step)
    def find_img_rel_path(self, path, count=10, confidence=0.95, region=None, grayscale=False, step=5):
        abs_path = os.path.join(os.path.join(os.path.dirname(__file__), "image"), path)
        return self.find_img_abs_path(abs_path, count, confidence=confidence, region=region, grayscale=grayscale,
                                      step=step)

    def compute_abs_position(self,i_x,i_y):
        x_of = i_x - self.init_width/2
        y_of = i_y - self.init_height/2
        return self.compute_position(x_of, y_of)

    def compute_position(self, x_offset, y_offset):
        y = int(self.window.top + (self.init_height / 2 + y_offset) * (self.window.height / self.init_height))
        x = int(self.window.left + (self.init_width / 2 + x_offset) * (self.window.width / self.init_width))
        return x, y

    def shopping(self, x,y,num="1",zero_num=4, shift_click=True):
        if type(num) == int :
            num = str(num)
        time.sleep(0.5)
        pdi.moveTo(x, y, duration=0.1)
        if shift_click : pdi.keyDown("shift")
        pdi.mouseDown(button="left")
        pdi.mouseUp(button="left")
        if shift_click : pdi.keyUp("shift")
        pdi.press(num)
        for i in range(0, zero_num):
            pdi.press("0")
        a = int(x - 31*(self.window.width / self.init_width))
        b = int(y + 15* (self.window.height / self.init_height))
        pdi.moveTo(a, b, duration=0.1)
        pdi.mouseDown(button="left")
        pdi.mouseUp(button="left")
        time.sleep(0.1)
        pdi.mouseDown(button="left")
        pdi.mouseUp(button="left")
    @classmethod
    def load_yaml(cls, yaml_file):
        if os.path.isfile(yaml_file):
            with open(yaml_file, "r", encoding="utf-8") as f:
                data = yaml.load(f, Loader=yaml.FullLoader)
            return data
        else:
            raise FileNotFoundError(f"未找到配置文件：{yaml_file}")

    def hold_key(self, duration, key):
        try:
            pdi.press(key)
            pdi.keyDown(key)
            time.sleep(duration)
        finally:
            pdi.keyUp(key)

    def into_abyss(self, map_name, unselect_image, select_comm_image, select_dy_image, max_find_ct=15, auto_into=True):
        # 进图
        print(f"开始进入{map_name}")
        self.hold_key(2, "right")
        time.sleep(1)
        pdi.press("f11")
        for i in range(0, 4): pdi.press("right")
        is_selected = False
        is_dy = False
        for i in range(0, max_find_ct):
            if self.find_img_rel_path(unselect_image) and not is_selected:
                pdi.press("up")
                is_selected = True
                print(f"已经切换到地图{map_name}")
                continue
            elif self.find_img_rel_path(select_comm_image) and not is_dy:
                print(f"已经切换到地图{map_name}的普通模式")
                for b in range(0, 4): pdi.press("right")
                is_dy = True
                continue

            elif self.find_img_rel_path(select_dy_image):
                print(f"已经切换到地图{map_name}的地狱模式")
                break
            else:
                if i >= max_find_ct - 1:
                    print(f"未找到对应地图{map_name}，所在城镇是否正确")
                    return False
                #pdi.press("up")

        for i in range(0, 4): pdi.press("right")
        if self.find_img_rel_path(select_dy_image):
            print(f"已经切换到地图{map_name}的地狱模式")
            if auto_into:
                pdi.press("space")
            return True
        return False

    def is_big_abyss(self, big_niu_image, small_niu_image, max_retry: int = 10):
        is_big_niu = False
        for i in range(0, max_retry):
            if self.find_img_rel_path(big_niu_image):
                is_big_niu = True
                break
            if self.find_img_rel_path(small_niu_image):
                is_big_niu = False
                break
            if i >= max_retry:
                print("深渊类型判断错误，请确认")
            time.sleep(0.5)
        return is_big_niu


    def get_house_default_image_name(self, is_big_niu, house_name):
        image_end = "" if is_big_niu else "-2"
        into_image_name_default = "{}-into{}.png".format(house_name, image_end)
        out_image_name_default = "{}-out{}.png".format(house_name, image_end)
        return into_image_name_default, out_image_name_default

    def into_house_check(self, name, into_image_name,max_retry=50):
        i = 0
        while i < max_retry:
            if self.find_img_rel_path(into_image_name):
                print(f"进入房间：{name}，开始操作")
                return True
            time.sleep(0.3)
        return False

    def out_house_before_check(self,name, out_image_name,out_image_pt,out_image_boss,finish_image, reclean=None,max_check=20 ):
        for i in range(0, max_check):
            if self.find_img_rel_path(out_image_name) and (
                    self.find_img_rel_path(out_image_pt, count=5) or self.find_img_rel_path(out_image_boss,count=5)
                    or self.find_img_rel_path(finish_image,count=5)):
                print(f"房间：{name}，清理完成")
                print("停止记录操作")
                return True
            if i >= max_check - 2:
                reclean()
            time.sleep(0.3)
        return False

    def house_action(self, name, is_big_niu, out_image_pt, out_image_boss, finish_image, clean_house=None,
                     out_house=None, max_check=50, reclean=None, special_out_image=None,special_into_image=None):

        into_image_name_default, out_image_name_default = self.get_house_default_image_name(is_big_niu, name)
        out_image_name = special_out_image if special_out_image is not None else out_image_name_default
        into_image_name = special_into_image if special_into_image is not None else into_image_name_default
        if not self.into_house_check(name,into_image_name, max_check):
            print(f"进入房间{name}失败")
            return False
        else :
            clean_house()
        if out_house is not None and self.out_house_before_check(name,out_image_name,out_image_pt,out_image_boss, finish_image, reclean=reclean):
            out_house()

    def release_key(self, key, action_time):
        pdi.press(key)
        time.sleep(action_time)

